using Random
# 定义DMRSType结构体
struct DMRSType
    DMRSCongfigurationType::Float64
    DMRSReferencePoints::String
    NumCDMGroupsWithoutData::Float64
    DMRSdownlinkR16::Bool
    DMRSTypeAPosition::Float64
    DMRSAdditionalPosition::Float64
    DMRSLength::Float64
    CustomSymbolSet::Matrix{Float64}
    DMRSPortSet::Float64
    NIDNSCID::Matrix{Float64}
    NISCID::Float64
    DMRSEnhancedR18::Bool
    CDMGroups::Float64
    DeltaShifts::Float64
    FrequencyWeights::Matrix{Float64}
    TimeWeights::Matrix{Float64}
    DMRSSubcarrierLocations::Matrix{Float64}
    CDMLengths::Matrix{Float64}
end

# 定义ReservedConfig结构体
struct nrPDSCHReservedConfigType
    PRBSet::Vector{Float64}
    SymbolSet::Vector{Float64}
    Period::Vector{Float64}
end
# 定义PTRSType结构体，包含图中所示的PTRS相关属性
struct PTRSType
    PTRSPortSet::Matrix{Float64}
    TimeDensity::Float64
    FrequencyDensity::Float64
    REOffset::String
end
# 初始化ReservedConfig实例
reserved_config_instance = nrPDSCHReservedConfigType([], [], [])

# 定义 PDSCHConfig 结构体
struct PDSCHConfig
    ReservedRE::Matrix{Float64}
    NID::Matrix{Float64}
    NSizeBWP::Matrix{Float64}
    NStartBWP::Matrix{Float64}
    Modulation::String
    ReservedPRB::nrPDSCHReservedConfigType
    PRBSetType::String
    VRBToPRBInterleaving::Bool
    VRBBundleSize::Float64
    DMRS::DMRSType
    PTRS::PTRSType
    NumLayers::Float64
    MappingType::String
    SymbolAllocation::Vector{Float64}
    PRBSet::Matrix{Float64}
    RNTI::Float64
    EnablePTRS::Bool
    EnableCodewords::Float64
end

# 定义 PDSCHExtension 结构体
struct PDSCHExtension
    W::Array{ComplexF64, 3}
    PRGBundleSize::Float64
    TargetCodeRate::Float64
    XOverhead::Float64
end

# 定义 PDSCH 结构体，包含 Config 和 Extension 字段
struct PDSCH
    Config::PDSCHConfig
    Extension::PDSCHExtension
end
# 创建一个基础的 DMRSType 实例，根据需求设置初始值
base_dmrs = DMRSType(
    1,
    "CRB0",
    2,
    false,
    2,
    0,
    2,
    zeros(Float64, 0, 0),
    2.0,
    zeros(Float64, 0, 0),
    0,
    false,
    1,
    1,
    reshape([1, 1], 1, 2),  # 将一维数组转换为 1x2 矩阵
    reshape([1, 1], 1, 2),  # 将一维数组转换为 1x2 矩阵
    reshape([1, 3, 5, 7, 9, 11], 6, 1),  # 将一维数组转换为 6x1 矩阵
    reshape([1, 1], 1, 2)  # 将一维数组转换为 1x2 矩阵
)
# 创建一个基础的 PTRSType 实例，根据需求设置初始值
base_ptrs = PTRSType(
    zeros(Float64, 0, 0),
    1,
    2,
    "00"
)
# 初始化 PDSCHConfig 结构体实例
function initialize_PDSCHConfig()
    ReservedRE = zeros(Float64, 0, 0)
    NID = zeros(Float64, 0, 0)
    NSizeBWP = zeros(Float64, 0, 0)
    NStartBWP = zeros(Float64, 0, 0)
    Modulation = "64QAM"
    ReservedPRB = reserved_config_instance
    PRBSetType = "VRB"
    VRBToPRBInterleaver = false
    VRBBundleSize = 1.0
    DMRS = base_dmrs
    PTRS = base_ptrs
    NumLayers = 0
    MappingType = "A"
    SymbolAllocation = [0, 10]
    PRBSet = reshape([0, 1, 4, 5, 6, 7, 10, 11, 30, 31, 34, 35, 38, 39, 44, 45, 48, 49], 18, 1)
    RNTI = 0
    EnablePTRS = false
    NumCodewords = 0

    return PDSCHConfig(
        ReservedRE,
        NID,
        NSizeBWP,
        NStartBWP,
        Modulation,
        ReservedPRB,
        PRBSetType,
        VRBToPRBInterleaver,
        VRBBundleSize,
        DMRS,
        PTRS,
        NumLayers,
        MappingType,
        SymbolAllocation,
        PRBSet,
        RNTI,
        EnablePTRS,
        NumCodewords
    )
end

# 初始化 PDSCHExtension 结构体实例
function initialize_PDSCHExtension()
    W = zeros(ComplexF64, 1, 256, 26)
    PRGBundleSize = 2
    TargetCodeRate = 0.7539
    XOverhead = 0

    return PDSCHExtension(
        W,
        PRGBundleSize,
        TargetCodeRate,
        XOverhead
    )
end

# 初始化 PDSCHs 结构体数组
function initialize_PDSCHs()
    num_elements = 5
    PDSCHs = Vector{PDSCH}(undef, num_elements)

    for i in 1:num_elements
        config = initialize_PDSCHConfig()
        extension = initialize_PDSCHExtension()
        PDSCHs[i] = PDSCH(config, extension)
    end

    return PDSCHs
end

# 创建 PDSCHs 结构体数组实例
PDSCHs_instance = initialize_PDSCHs()
# 定义nrCarrierConfig结构体
struct nrCarrierConfig
    NCELLID::Float64
    NSizeGrid::Float64
    NStartGrid::Float64
    NSlot::Float64
    NFrame::Float64
    IntraCellGuardBands::Matrix{Float64}
    SymbolsPerSlot::Float64
    SlotsPerSubframe::Float64
    SlotsPerFrame::Float64
    SubcarrierSpacing::Float64
    CyclicPrefix::String
end

# 创建nrCarrierConfig实例并赋初值
carrier = nrCarrierConfig(
    1,
    51,
    0,
    199,
    0,
    zeros(Float64, 0, 2),
    14,
    2,
    20,
    30,
    "normal"
)
bsAntSize = [16, 8, 2]
B = zeros(Float64, 0, 0)

function hMultiDLTransmit(carrier, PDSCHs, bsAntSize, B)
    # Create transmit resource grid
    nTxAnts = prod(bsAntSize)
    dlGrid = nrResourceGrid(carrier, nTxAnts, OutputDataType=Float32)

    numUEs = length(PDSCHs)
    txSymbols = Vector{Any}(undef, numUEs)
    singleLayerTBS = NaN

    # For each UE
    for ue in 1:numUEs
        # Extract the configuration for this UE
        pdsch = PDSCHs[ue].Config
        pdschExt = PDSCHs[ue].Extension

        # Create the PDSCH indices
        indices, indicesInfo = nrPDSCHIndices(carrier, pdsch)

        # Calculate transport block size and create transport block
        TBS = nrTBS(pdsch.Modulation, pdsch.NumLayers, length(pdsch.PRBSet), indicesInfo[:NREPerPRB], pdschExt.TargetCodeRate, pdschExt.XOverhead)
        trblk = rand(0:1, TBS)

        # For the first UE, calculate the single-layer transport block size
        # for a full RB allocation, used for capacity calculation
        if ue == 1
            singleLayerTBS = nrTBS(pdsch.Modulation, 1, carrier.NSizeGrid, indicesInfo[:NREPerPRB], pdschExt.TargetCodeRate, pdschExt.XOverhead)
        end

        # Perform DL-SCH encoding
        encodeDLSCH = nrDLSCH(pdschExt.TargetCodeRate)
        setTransportBlock(encodeDLSCH, trblk)
        RV = 0
        cws = encodeDLSCH(pdsch.Modulation, pdsch.NumLayers, indicesInfo[:G], RV)

        # Perform PDSCH modulation
        symbols = nrPDSCH(carrier, pdsch, cws)
        txSymbols[ue] = symbols

        # Apply beamforming and map to the transmit grid
        antSymbols, antIndices = nrPDSCHPrecode(carrier, symbols, indices, pdschExt.W)
        dlGrid[antIndices] = dlGrid[antIndices] + antSymbols

        # Create the PDSCH DM-RS
        dmrsIndices = nrPDSCHDMRSIndices(carrier, pdsch)
        dmrsSymbols = nrPDSCHDMRS(carrier, pdsch)

        # Apply beamforming and map to the transmit grid
        dmrsAntSymbols, dmrsAntIndices = nrPDSCHPrecode(carrier, dmrsSymbols, dmrsIndices, pdschExt.W)
        dlGrid[dmrsAntIndices] = dlGrid[dmrsAntIndices] + dmrsAntSymbols
    end

    # Create the output structure containing the waveform, resource grid,
    # and OFDM information
    txDL = Dict()
    txDL[:dlWaveform] = nrOFDMModulate(carrier, dlGrid)
    if B !== nothing && !isempty(B)
        txDL[:dlWaveform] = txDL[:dlWaveform] * B
    end

    txDL[:dlGrid] = dlGrid
    txDL[:ofdmInfo] = nrOFDMInfo(carrier)

    return txDL, txSymbols, singleLayerTBS
end